package com.oocl.euc.core.requestform.service;

import com.oocl.euc.authentication.core.SSOUserContext;
import com.oocl.euc.common.constant.ApplicationConstant;
import com.oocl.euc.common.constant.MailTemplateKey;
import com.oocl.euc.common.utils.EntityMapToVOUtil;
import com.oocl.euc.common.utils.UserContextHolder;
import com.oocl.euc.core.attachment.model.Attachment;
import com.oocl.euc.core.maintenance.model.EmailTemplate;
import com.oocl.euc.core.maintenance.repository.EmailTemplateRepository;
import com.oocl.euc.core.requestform.model.RequestAttachment;
import com.oocl.euc.core.requestform.model.RequestForm;
import com.oocl.euc.core.requestform.model.RequestRemarks;
import com.oocl.euc.core.requestform.model.RequestRemarksAttach;
import com.oocl.euc.core.requestform.repository.RequestFormRepository;
import com.oocl.euc.core.requestform.repository.RequestRemarksRepository;
import com.oocl.euc.core.requestform.vo.ConversationHistoryVO;
import com.oocl.euc.core.requestform.vo.RequestRemarksVO;
import com.oocl.euc.framework.base.persistence.IBaseRepository;
import com.oocl.euc.framework.base.service.BaseService;
import com.oocl.euc.framework.common.utils.CollectionUtils;
import com.oocl.euc.framework.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RequestRemarksService extends BaseService<RequestRemarks, Long> {
    private Logger logger = LoggerFactory.getLogger(RequestRemarksService.class);

    @Autowired
    private RequestRemarksRepository requestRemarksRepository;

    @Autowired
    private EmailSenderService emailSenderService;

    @Autowired
    private EmailTemplateRepository emailTemplateRepository;

    @Autowired
    private RequestFormRepository requestFormRepository;

    @Override
    protected IBaseRepository<RequestRemarks, Long> getRepository() {
        return requestRemarksRepository;
    }


    public RequestRemarksRepository getRequestRemarksRepository() {
        return requestRemarksRepository;
    }

    public EmailSenderService getEmailSenderService() {
        return emailSenderService;
    }

    public RequestFormRepository getRequestFormRepository() {
        return requestFormRepository;
    }

    public EmailTemplateRepository getEmailTemplateRepository() {
        return emailTemplateRepository;
    }

    @Transactional
    public RequestRemarks addOneConversationRequestRemarks(RequestRemarksVO requestRemarksVO) throws Exception {
        RequestRemarks requestRemarks = EntityMapToVOUtil.map(requestRemarksVO, RequestRemarks.class);
        SSOUserContext userContext = UserContextHolder.getUserContext();
        requestRemarks.setDescription(requestRemarksVO.getDesc());
        List<RequestRemarksAttach> requestRemarksAttachList = new ArrayList<>();
        requestRemarksVO.getAttachmentsList().forEach(attachment -> {
            RequestRemarksAttach requestRemarksAttach = new RequestRemarksAttach();
            requestRemarksAttach.setAttachment(attachment);
            requestRemarksAttachList.add(requestRemarksAttach);
        });
        if (StringUtils.isEmpty(requestRemarksVO.getSender())) {
            requestRemarks.setSender(userContext.getUserInfo().getDomainId());
        }
        requestRemarks.setDisplayName(userContext.getUserInfo().getDisplayName());
        requestRemarks.setRequestRemarksAttachList(requestRemarksAttachList);
        RequestRemarks r = this.save(requestRemarks);
        sendEmailWhenAddRequestRemarks(r, requestRemarksVO.getAttachmentsList());
        logger.info("request remark and email have sent");
        return r;
    }

    public List<ConversationHistoryVO> findConversationHistoryVOByRefNo(String refNo) {
        List<RequestRemarks> requestRemarks = requestRemarksRepository.findByRefNo(refNo);
        List<ConversationHistoryVO> returnList = new ArrayList<>();
        requestRemarks.forEach(r -> {
            ConversationHistoryVO conversationHistoryVO = EntityMapToVOUtil.map(r, ConversationHistoryVO.class);
            List<Attachment> attachmentList = r.getRequestRemarksAttachList().stream().map(RequestRemarksAttach::getAttachment).collect(Collectors.toList());
            conversationHistoryVO.setAttachmentList(attachmentList);
            returnList.add(conversationHistoryVO);
        });
        return returnList;
    }

    private RequestForm findRequestFormByRefNo(String refNo) {
        return requestFormRepository.findByRefNO(refNo);
    }

    private void sendEmailWhenAddRequestRemarks(RequestRemarks requestRemarks, List<Attachment> attachmentList) throws Exception {
        RequestForm requestForm = findRequestFormByRefNo(requestRemarks.getRefNo());
        String requestFormStatus = requestForm.getRequestStatus();
        String sendToCC = requestRemarks.getSendToCC();
        EmailTemplate emailTemplate = emailTemplateRepository.findByEmailTempalteKey(MailTemplateKey.CONVERSATION_EMAIL);
        if (emailTemplate != null) {
            emailTemplate.setContent(requestRemarks.getDescription());
            emailTemplate.setSendTo(getEmailTemplateReceiversString(requestRemarks.getReceiver(), requestFormStatus));
            emailTemplate.setSendFrom(requestRemarks.getSender());
            if (StringUtils.isNotEmpty(sendToCC)) {
                emailTemplate.setEmailCC(getEmailTemplateReceiversString(sendToCC, requestFormStatus));
            }
            emailSenderService.send(emailTemplate, requestForm, attachmentList);

        }
    }

    private String getEmailTemplateReceiversString(String receiver, String requestFormStatus) {
        StringBuilder stringBuilder = new StringBuilder();
        Map<String, String> emailTemplateMap = ApplicationConstant.getSendConversationEmailToAndBCCRelatedMap(requestFormStatus);
        for (Map.Entry<String, String> entry : emailTemplateMap.entrySet()) {
            String key = entry.getKey().toString();
            String value = entry.getValue().toString();
            if (receiver.contains(ApplicationConstant.CONVERSATION_EMAIL_ROLE_ALL)) {
                stringBuilder.append(value);
            } else {
                if (receiver.contains(key)) {
                    stringBuilder.append(value);
                }
            }
        }
        return stringBuilder.toString();
    }

    public void saveRemark(RequestForm requestForm, String emailTemplateKey) {
        saveRemark(requestForm, emailTemplateKey, null);
    }

    public void saveRemark(RequestForm requestForm, String emailTemplateKey, List<Attachment> attachmentList) {
        EmailTemplate template = emailTemplateRepository.findByEmailTempalteKey(emailTemplateKey);
        if (template != null) {
            EmailTemplate mappedTemplate = emailSenderService.mapEmailTemplate(template, requestForm);
            this.saveRemarkWithMappedTemplate(requestForm, mappedTemplate, attachmentList);
        }
    }

    public RequestRemarks saveRemarkWithMappedTemplate(RequestForm requestForm, EmailTemplate mappedTemplate) {
        return saveRemarkWithMappedTemplate(requestForm, mappedTemplate, null);
    }

    public RequestRemarks saveRemarkWithMappedTemplate(RequestForm requestForm, EmailTemplate mappedTemplate, List<Attachment> attachmentList) {
        RequestRemarks remark = new RequestRemarks();
        try {
            remark.setSender(mappedTemplate.getSendFrom());
            remark.setReceiver(mappedTemplate.getSendTo());
            remark.setDescription(mappedTemplate.getContent());
            remark.setRefNo(requestForm.getRefNO());
            remark.setUpdatedBy(requestForm.getUpdatedBy());
            if (mappedTemplate.getContent() != null) {
                if (mappedTemplate.getContent().contains("${UPDATE_BY}") && !emailSenderService.needSendEmail(requestForm)) {
                    remark.setDescription(mappedTemplate.getContent().replace("${UPDATE_BY}", requestForm.getUpdatedBy().getDomainId()));
                }
            }
            List<RequestRemarksAttach> requestRemarksAttachList = new ArrayList<>();
            List<RequestAttachment> attachments;
            if (CollectionUtils.isEmpty(attachmentList)) {
                attachments = requestForm.getRequestattachments();
                if (CollectionUtils.isNotEmpty(attachments)) {
                    attachments.stream().map(attachment -> {
                        RequestRemarksAttach requestRemarksAttach = new RequestRemarksAttach();
                        requestRemarksAttach.setAttachment(attachment.getAttachment());
                        return requestRemarksAttachList.add(requestRemarksAttach);
                    }).collect(Collectors.toList());
                }
            } else {
                attachmentList.stream().map(attachment -> {
                    RequestRemarksAttach requestRemarksAttach = new RequestRemarksAttach();
                    requestRemarksAttach.setAttachment(attachment);
                    return requestRemarksAttachList.add(requestRemarksAttach);
                }).collect(Collectors.toList());
            }

            remark.setRequestRemarksAttachList(requestRemarksAttachList);
            this.requestRemarksRepository.save(remark);
        } catch (Exception ex) {
            logger.error("Error in saving remark [" + requestForm.getRefNO() + "]");

        }
        return remark;
    }
}
